<template>
  <div class="maintenancePlanAdd">
    <div class="panel-body">
      <div class="position-contentor">
        <div />
      </div>
      <div class="demo">
        <div class="canvas-content">
          <div class="left"><button v-show="currenNum >1" @click="handleChange(-1)"><i
            class="el-icon-arrow-left"
          /></button></div>
          <div class="canvas-main">
            <canvas id="canvas" :width="width" :height="height" />
          </div>
          <div class="right"><button v-show="positionNum >currenNum" @click="handleChange(1)"><i
            class="el-icon-arrow-right"
          /></button></div>
        </div>
      </div>
      <div class="describe">
        <div class="describe-title">说明：</div>
        <div class="describe-value">
          <div>左键点击多次绘制多边形，右键选择绑定部位；</div>
          <div> 绘制多边形时，右键可撤销已绘制的点、enter键可以自动闭合多边形，Delete键可以删除选中区域</div>
        </div>

      </div>
      <div class="btn-contentor">
        <el-button type="primary" @click="clearCanvas">清空当前所有部位</el-button>
        <el-button type="primary" @click="save">保存</el-button>
        <el-button @click="detectList">关闭</el-button>
      </div>
    </div>
    <div v-show="isPersoncontextMenus" id="menu" ref="msgRightMenu">
      <ul>
        <li
          v-for="item in positionList"
          :key="item.fid"
          :class="[item.fid==currentId?'active':'',disabledItem(item.fid)?'is-disabled':'']"
          @click="selectChanged(item)"
        >{{ item.FNAME_L2 }}</li>
      </ul>
    </div>
  </div>
</template>
<script>
import { fabric } from 'fabric'
import { isPolygonsOverlap } from '@/utils/overlapping'
export default {
  name: 'CanvasDraw',
  props: {
    closeDialog: {
      type: Boolean,
      default: false
    },
    positionList: {
      type: Array,
      default() {
        return []
      }
    },
    groups: {
      type: Array,
      default() {
        return []
      }
    }
  },
  data() {
    return {
      width: 880,
      height: 520,
      rect: [],
      canvas: {},
      showMenu: false,
      x: '',
      y: '',
      mouseFrom: {},
      mouseTo: {},
      drawType: 'polygon', // 当前绘制图像的种类 默认多边形
      drawWidth: 2, // 笔触宽度
      color: '#E34F51', // 画笔颜色
      drawingObject: null, // 当前绘制对象
      moveCount: 1, // 绘制移动计数器
      doDrawing: false, // 绘制状态

      // polygon 相关参数
      polygonMode: true, // 默认多边形
      pointArray: [],
      lineArray: [],
      activeShape: false,
      activeLine: '',
      line: {},

      groupList: [], // 多边形组合数组
      imgList: [],
      imgSizeList: [], // 图片大小数组
      currentId: '', // 当前部位id
      currentPoints: [], // 当前选中多边形
      positionNum: 1, // 部位图总数量
      currenNum: 1, // 当前操作部位图位置

      isPersoncontextMenus: false,
      originList: [] // 初始化数组
    }
  },
  watch: {
    closeDialog: {
      handler: function(val, oldval) {
        if (val === true) {
          this.detectList()
        }
      },
      deep: true // 对象内部的属性监听，也叫深度监听
    },
    drawType() {
      this.canvas.selection = !this.drawType
    },
    width() {
      this.canvas.setWidth(this.width)
    },
    height() {
      this.canvas.setHeight(this.height)
    }
  },
  created() {
    // 内容宽度
    this.width = parseInt(document.body.clientWidth * 0.6 - 120)
  },
  mounted() {
    this.mainCanvas()
    this.innitDraw()
  },
  // 销毁监听事件
  destroyed() {
    document.oncontextmenu = function() {
      return true
    }
  },
  methods: {
    clearCanvas() {
      const canvas = this.canvas.getObjects()

      for (let i = 1; i < canvas.length; i++) {
        this.canvas.remove(canvas[i])
      }
      this.groupList[this.currenNum - 1].value = []
    },
    // 清空画布
    resetDraw() {
      this.canvas.clear()
      this.width = parseInt(document.body.clientWidth * 0.6 - 120)
      this.height = 520
    },
    innitDraw() {
      if (document.querySelector('.upper-canvas')) {
        this.resetDraw()
        this.currenNum = 1
      }

      const list = JSON.parse(JSON.stringify(this.groups))
      const imgList = list.map(i => i.fileId)
      this.positionNum = imgList.length // 图片张数
      this.imgList = imgList
      this.groupList = list

      this.originList = this.groupList.map(i => ({
        id: i.id,
        fileId: i.fileId,
        points: i.points
      }))

      // 图片画布
      this.loadExpImg(0)
    },
    // 从已渲染的DOM元素加载图片至canvas
    loadExpImg(val) {
      // 超过可显示图
      if (val > this.imgList.length - 1) {
        this.width = parseInt(document.body.clientWidth * 0.6 - 120)
        this.height = 520
        return
      }
      var img = new Image()
      // 改变图片的src
      // TODO 更改获取图片的链接
      img.src = process.env.VUE_APP_BASE_API + '/file/download?fileKey=' + this.imgList[val] + '&EPID=jffc_zhcy'
      // img.src = 'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&t=' + Math.random()
      const _this = this
      // 判断是否有缓存
      if (img.complete) {
        _this.drawImg(val, img, img.width, img.height)
      } else {
        // 加载完成执行
        img.onload = function () {
          if (_this.currenNum > _this.imgSizeList.length) {
            _this.imgSizeList.push({ width: img.width, height: img.height })
          }
          _this.drawImg(val, img, img.width, img.height)
        }
      }
    },
    drawImg(val, imgElement, width, height) {
      let first = false
      let scale = 1
      if (width > parseInt(document.body.clientWidth * 0.6 - 120)) {
        scale = (document.body.clientWidth * 0.6 - 120) / width
      }
      if (this.groupList[val].scale === '') {
        first = true
        this.groupList[val].scale = scale
      }

      if (width > parseInt(document.body.clientWidth * 0.6 - 120)) {
        height = height * ((document.body.clientWidth * 0.6 - 120) / width)
        width = document.body.clientWidth * 0.6 - 120
      }
      this.canvas.setWidth(width)
      this.canvas.setHeight(height)
      var imgInstance = new fabric.Image(imgElement, {
        zIndex: -1,
        selectable: false,
        scaleX: scale,
        scaleY: scale
      })
      this.canvas.add(imgInstance)
      // 渲染完图片再渲染多边形
      this.groupList[val].value.forEach(item => {
        this.reversePolygon(item.points, item.name, first)
      })
    },
    // 已知点位画多边形
    reversePolygon(points, text, first) {
      if (first) {
        const size = this.imgSizeList[this.currenNum - 1]
        const scale = this.groupList[this.currenNum - 1].scale
        points.forEach(elem => {
          elem.x = (elem.x / 100) * size.width * scale
          elem.y = (elem.y / 100) * size.height * scale
        })
      }
      var polygon = new fabric.Polygon(points, {
        stroke: this.color,
        strokeWidth: this.drawWidth,
        fill: 'rgba(255, 255, 255, 0)',
        opacity: 1,
        hasBorders: true,
        hasControls: false, // 禁用画布矩形的控件
        selectable: true
      })
      // 中心点
      const centerPoint = {
        x: 0,
        y: 0
      }
      points.forEach(elem => {
        if (centerPoint.x === 0 || centerPoint.x > elem.x) {
          centerPoint.x = elem.x
        }
        if (centerPoint.y === 0 || centerPoint.y > elem.y) {
          centerPoint.y = elem.y
        }
      })
      // 绘制文本 // fabric.Textbox
      const texts = new fabric.Text(text, {
        fontSize: 20,
        fill: '#000',
        left: centerPoint.x + polygon.width / 2,
        top: centerPoint.y + polygon.height / 2,
        hasControls: false,
        width: polygon.width,
        height: polygon.height,
        splitByGrapheme: true, // 拆分中文，可以实现自动换行
        originX: 'center',
        originY: 'center'
      })
      // 进行组合
      var group = new fabric.Group([polygon, texts], {
        hasControls: false,
        lockMovementX: true,
        lockMovementY: true
      })
      this.canvas.add(group)
      // 调用渲染方法
      this.canvas.renderAll()
    },
    // 鼠标按下时触发
    mousedown(e) {
      this.isPersoncontextMenus = false
      this.changActive()
      // 记录鼠标按下时的坐标
      var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)

      // this.judge(dot,coordinates)
      this.mouseFrom.x = xy.x
      this.mouseFrom.y = xy.y
      this.doDrawing = true
      // 绘制多边形
      if (this.drawType === 'polygon') {
        this.canvas.skipTargetFind = false
        try {
          // 此段为判断是否闭合多边形，点击红点时闭合多边形
          if (this.pointArray.length > 1) {
            // e.target.id == this.pointArray[0].id 表示点击了初始红点
            if (e.target && e.target.id === this.pointArray[0].id) {
              if (this.groupList[this.currenNum - 1].value.length > 0) {
                let include = false
                this.groupList[this.currenNum - 1].value.forEach(elem => {
                  const pointList = JSON.parse(JSON.stringify(elem.points))
                  pointList.push(elem.points[0])
                  include = include || this.judge(xy, pointList)
                })
                if (!include) {
                  this.generatePolygon()
                  return
                }
              } else {
                this.generatePolygon()
                return
              }
            }
          }
          // 未点击红点则继续作画
          if (this.polygonMode) {
            if (this.groupList[this.currenNum - 1].value.length > 0) {
              let include = false
              this.groupList[this.currenNum - 1].value.forEach(elem => {
                const pointList = JSON.parse(JSON.stringify(elem.points))
                pointList.push(elem.points[0])
                include = include || this.judge(xy, pointList)
              })
              if (!include) {
                this.addPoint(e)
              }
            } else {
              this.addPoint(e)
            }
          }
        } catch (error) {
          console.log(error)
        }
      }
    },
    // 鼠标松开执行
    mouseup(e) {
      var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)
      this.mouseTo.x = xy.x
      this.mouseTo.y = xy.y
      this.drawingObject = null
      this.moveCount = 1
      if (this.drawType !== 'polygon') {
        this.doDrawing = false
      }
    },
    // 鼠标移动过程中已经完成了绘制
    mousemove(e) {
      if (this.moveCount % 2 && !this.doDrawing) {
        // 减少绘制频率
        return
      }
      this.moveCount++
      var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)
      this.mouseTo.x = xy.x
      this.mouseTo.y = xy.y
      // 多边形与文字框特殊处理
      if (this.drawType !== 'polygon') {
        this.drawing(e)
      }
      if (this.drawType === 'polygon') {
        if (this.activeLine && this.activeLine.class === 'line') {
          var pointer = this.canvas.getPointer(e.e)
          this.activeLine.set({
            x2: pointer.x,
            y2: pointer.y
          })

          var points = this.activeShape.get('points')
          points[this.pointArray.length] = {
            x: pointer.x,
            y: pointer.y,
            zIndex: 1
          }
          this.activeShape.set({
            points: points
          })
          this.canvas.renderAll()
        }
        // 调用渲染方法
        this.canvas.renderAll()
      }
    },
    /**
       * @param  dot {{x,y}} 需要判断的点
       * @param  coordinates {{x,y}[]} 多边形点坐标的数组，为保证图形能够闭合，起点和终点必须相等。
       *        比如三角形需要四个点表示，第一个点和最后一个点必须相同。
       * @param
       */
    judge(dot, coordinates, noneZeroMode) {
      // 默认启动none zero mode
      noneZeroMode = noneZeroMode || 1
      var x = dot.x
      var y = dot.y
      var crossNum = 0
      // 点在线段的左侧数目
      var leftCount = 0
      // 点在线段的右侧数目
      var rightCount = 0
      for (var i = 0; i < coordinates.length - 1; i++) {
        var start = coordinates[i]
        var end = coordinates[i + 1]
        // 起点、终点斜率不存在的情况
        if (start.x === end.x) {
          // 因为射线向右水平，此处说明不相交
          if (x > start.x) continue

          // 从左侧贯穿
          if ((end.y > start.y && y >= start.y && y <= end.y)) {
            leftCount++
            crossNum++
          }
          // 从右侧贯穿
          if ((end.y < start.y && y >= end.y && y <= start.y)) {
            rightCount++
            crossNum++
          }
          continue
        }
        // 斜率存在的情况，计算斜率
        var k = (end.y - start.y) / (end.x - start.x)
        // 交点的x坐标
        var x0 = (y - start.y) / k + start.x
        // 因为射线向右水平，此处说明不相交
        if (x > x0) continue

        if ((end.x > start.x && x0 >= start.x && x0 <= end.x)) {
          crossNum++
          if (k >= 0) leftCount++
          else rightCount++
        }
        if ((end.x < start.x && x0 >= end.x && x0 <= start.x)) {
          crossNum++
          if (k >= 0) rightCount++
          else leftCount++
        }
      }
      return noneZeroMode === 1 ? leftCount - rightCount !== 0 : crossNum % 2 === 1
    },
    deleteObj() {
      this.canvas.getActiveObjects().map(item => {
        let option = -1
        this.groupList[this.currenNum - 1].value.forEach((items, index) => {
          if (items.points === item._objects[0].points) {
            option = index
          }
        })
        if (option !== -1) {
          this.groupList[this.currenNum - 1].value.splice(option, 1)
        }
        this.canvas.remove(item)
      })
    },
    transformMouse(mouseX, mouseY) {
      return {
        x: mouseX / 1,
        y: mouseY / 1
      }
    },
    addPoint(e) {
      var random = Math.floor(Math.random() * 10000)
      var id = new Date().getTime() + random
      var circle = new fabric.Circle({
        radius: 5,
        fill: '#ffffff',
        stroke: '#333333',
        strokeWidth: 0.5,
        left: (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
        top: (e.pointer.y || e.e.layerY) / this.canvas.getZoom(),
        selectable: false,
        hasBorders: false,
        hasControls: false,
        originX: 'center',
        originY: 'center',
        id: id,
        objectCaching: false
      })
      if (this.pointArray.length === 0) {
        circle.set({
          fill: 'red'
        })
      }
      var points = [
        (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
        (e.pointer.y || e.e.layerY) / this.canvas.getZoom(),
        (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
        (e.pointer.y || e.e.layerY) / this.canvas.getZoom()
      ]

      this.line = new fabric.Line(points, {
        strokeWidth: 2,
        fill: '#999999',
        stroke: '#999999',
        class: 'line',
        originX: 'center',
        originY: 'center',
        selectable: false,
        hasBorders: false,
        hasControls: false,
        evented: false,

        objectCaching: false
      })
      if (this.activeShape) {
        var pos = this.canvas.getPointer(e.e)
        const points = this.activeShape.get('points')
        points.push({
          x: pos.x,
          y: pos.y
        })
        var polygon = new fabric.Polygon(points, {
          stroke: '#333333',
          strokeWidth: 1,
          fill: '#cccccc',
          opacity: 0.3,

          selectable: false,
          hasBorders: false,
          hasControls: false,
          evented: false,
          objectCaching: false
        })
        this.canvas.remove(this.activeShape)
        this.canvas.add(polygon)
        this.activeShape = polygon
        this.canvas.renderAll()
      } else {
        var polyPoint = [{
          x: (e.pointer.x || e.e.layerX) / this.canvas.getZoom(),
          y: (e.pointer.y || e.e.layerY) / this.canvas.getZoom()
        }]
        const polygon = new fabric.Polygon(polyPoint, {
          stroke: '#333333',
          strokeWidth: 1,
          fill: '#cccccc',
          opacity: 0.3,

          selectable: false,
          hasBorders: false,
          hasControls: false,
          evented: false,
          objectCaching: false
        })
        this.activeShape = polygon
        this.canvas.add(polygon)
      }
      this.activeLine = this.line

      this.pointArray.push(circle)
      this.lineArray.push(this.line)
      this.canvas.add(this.line)
      this.canvas.add(circle)
    },
    generatePolygon() {
      // 多边形点集合
      var points = []
      this.pointArray.map((point, index) => {
        points.push({
          x: point.left,
          y: point.top
        })
        this.canvas.remove(point)
      })
      this.lineArray.map((line, index) => {
        this.canvas.remove(line)
      })
      this.canvas.remove(this.activeShape).remove(this.activeLine)

      const list = this.groupList[this.currenNum - 1].value
      if (list.length > 0) {
        const pointsA = []
        points.forEach((item, index) => {
          pointsA.push([item.x, item.y])
        })
        let overlapping = false
        list.forEach(item => {
          const pointsB = []
          item.points.forEach((item, index) => {
            pointsB.push([item.x, item.y])
          })
          overlapping = overlapping || isPolygonsOverlap(pointsA, pointsB)
        })
        if (overlapping) {
          this.$message.error(`图形不能相交`)
          this.activeLine = null
          this.activeShape = null
          this.doDrawing = false
          // 重新处理多边形
          this.pointArray = [] // 顶点集合
          this.lineArray = []
          this.canvas.renderAll()
          return
        }
      }

      var polygon = new fabric.Polygon(points, {
        stroke: this.color,
        strokeWidth: this.drawWidth,
        fill: 'rgba(255, 255, 255, 0)',
        opacity: 1,
        hasBorders: true,
        hasControls: false, // 禁用画布矩形的控件
        selectable: true
      })
      // 中心点
      const centerPoint = {
        x: 0,
        y: 0
      }
      points.forEach(elem => {
        if (centerPoint.x === 0 || centerPoint.x > elem.x) {
          centerPoint.x = elem.x
        }
        if (centerPoint.y === 0 || centerPoint.y > elem.y) {
          centerPoint.y = elem.y
        }
      })
      // 绘制文本 // fabric.Textbox
      var text = new fabric.Text('', {
        fontSize: 20,
        fill: '#000',
        left: centerPoint.x + polygon.width / 2,
        top: centerPoint.y + polygon.height / 2,
        hasControls: false,
        width: polygon.width,
        height: polygon.height,
        splitByGrapheme: true, // 拆分中文，可以实现自动换行
        originX: 'center',
        originY: 'center'
      })
      // this.canvas.add(text);

      // 进行组合
      var group = new fabric.Group([polygon, text], {
        hasControls: false,
        lockMovementX: true,
        lockMovementY: true
      })
      this.canvas.add(group)
      // this.canvas.add(polygon);
      this.groupList[this.currenNum - 1].value.push({
        points: points,
        id: '',
        name: ''
      })

      this.activeLine = null
      this.activeShape = null
      this.doDrawing = false

      // 重新处理多边形
      this.pointArray = [] // 顶点集合
      this.lineArray = []

      // 1: 获得画布上的所有对象：
      const items = this.canvas.getObjects()
      // 2: 设置画布上的某个对象为活动对象。
      this.canvas.setActiveObject(items[items.length - 1])
      this.changActive()
      // this.canvas.setActiveObject()
    },
    changActive() {
      // 当前选择项
      const object = this.canvas.getActiveObjects()
      if (object.length === 0) {
        // 当前选中项清除
        this.currentId = ''
      } else if (object.length > 0 && object[0]._objects) {
        // 当前选择项
        this.currentPoints = object[0]._objects[0].points
        const option = this.groupList[this.currenNum - 1].value.filter(elem => {
          return elem.points === this.currentPoints
        })
        this.currentId = option[0].id
      }
    },
    drawing(e) {
      if (this.drawingObject) {
        this.canvas.remove(this.drawingObject)
      }
      var canvasObject = null
      var left = this.mouseFrom.x
      var top = this.mouseFrom.y
      var mouseFrom = this.mouseFrom
      var mouseTo = this.mouseTo
      switch (this.drawType) {
        case 'rectangle': // 长方形
          // 按shift时画正方型
          if (e.e.shiftKey) {
            mouseTo.x - left > mouseTo.y - top ? mouseTo.y = top + mouseTo.x - left : mouseTo.x = left + mouseTo.y -
                top
          }
          var path =
              'M ' +
              mouseFrom.x +
              ' ' +
              mouseFrom.y +
              ' L ' +
              mouseTo.x +
              ' ' +
              mouseFrom.y +
              ' L ' +
              mouseTo.x +
              ' ' +
              mouseTo.y +
              ' L ' +
              mouseFrom.x +
              ' ' +
              mouseTo.y +
              ' L ' +
              mouseFrom.x +
              ' ' +
              mouseFrom.y +
              ' z'
          canvasObject = new fabric.Path(path, {
            left: left,
            top: top,
            stroke: this.color,
            strokeWidth: this.drawWidth,
            fill: 'rgba(255, 255, 255, 0)',
            hasControls: false
          })
          // 也可以使用fabric.Rect
          break
        default:
          break
      }
      // 正方形
      if (canvasObject) {
        this.canvas.add(canvasObject)
        this.drawingObject = canvasObject
      }
    },
    // 选择改变
    selectChanged(item) {
      const val = item.fid
      this.currentId = val
      this.isPersoncontextMenus = false
      if (this.currentPoints) {
        let position = -1
        this.groupList[this.currenNum - 1].value.forEach((item, index) => {
          if (item.points === this.currentPoints) {
            position = index
          }
        })
        if (position !== -1) {
          let option = this.positionList.filter(elem => {
            return elem.fid === val
          })
          // 选择空项
          if (option.length === 0) {
            option = [{
              id: '',
              FNAME_L2: '',
              layout_space_id: '',
              layout_id: ''
            }]
          }
          this.groupList[this.currenNum - 1].value[position].id = val
          this.groupList[this.currenNum - 1].value[position].name = option[0].FNAME_L2
          this.groupList[this.currenNum - 1].value[position].layoutSpaceId = option[0].layout_space_id
          this.groupList[this.currenNum - 1].value[position].layoutId = option[0].layout_id
          // 显示文字
          this.canvas.getActiveObjects()[0].item(1).set({
            text: option[0].FNAME_L2
          })
          // 重新渲染
          this.canvas.renderAll()
        }
      }
    },
    detectList() {
      // 移动后的偏移量没有被记住
      // const objects = this.canvas.getObjects()
      const list = []
      this.groupList.forEach((elem, index) => {
        elem.value.forEach(item => {
          // 偏移量
          item.points.forEach(items => {
            if (elem.scale !== '') {
              items.x = (((items.x * elem.scale) / this.imgSizeList[index].width) * 100).toFixed(4)
              items.y = (((items.y * elem.scale) / this.imgSizeList[index].height) * 100).toFixed(4)
            }
          })
          list.push({
            id: item.id,
            fileId: this.imgList[index].toString(),
            points: item.points
          })
        })
      })
      if (JSON.stringify(list) === JSON.stringify(this.originList)) {
        this.close()
      } else {
        this.$confirm('您有修改未保存是否继续关闭, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.close()
        }).catch(() => {
          this.$emit('colse', false)
          // this.closeDialog = false;
        })
      }
    },
    // 保存
    save() {
      if (this.imgList.length < 1) {
        this.$message.warning(`请上传户型图`)
        return
      }
      if (this.groupList.length < 1) {
        this.$message.warning(`请绘制部位图`)
        return
      }
      // 移动后的偏移量没有被记住
      // const objects = this.canvas.getObjects()
      const groupList = JSON.parse(JSON.stringify(this.groupList))
      this.$emit('save', { groupList })
      // this.$emit('colse', true)
    },
    close() {
      this.$emit('colse', true)
    },
    handleChange(val) {
      this.currentId = ''
      this.currenNum += val
      this.isPersoncontextMenus = false
      // 清空画布
      this.canvas.clear()
      this.loadExpImg(this.currenNum - 1)
    },
    mainCanvas() {
      this.canvas = new fabric.Canvas('canvas', {})
      this.canvas.selectionColor = 'rgba(0,0,0,0.05)'
      this.canvas.isDrawingMode = false
      this.canvas.on('mouse:down', this.mousedown)
      this.canvas.on('mouse:move', this.mousemove)
      this.canvas.on('mouse:up', this.mouseup)

      document.onkeydown = e => {
        // 键盘 delect删除所选元素
        if (e.keyCode === 46) {
          this.deleteObj()
        }
        if (e.keyCode === 13 && this.pointArray.length > 0) {
          if (this.pointArray.length >= 3) {
            this.generatePolygon()
          } else {
            this.$message.warning(`至少三个点才能确定一个多边形`)
          }
        }
      }

      // 去掉默认的contextmenu事件，否则会和右键事件同时出现。
      document.oncontextmenu = function(e) {
        e.preventDefault()
      }
      // 在canvas上层对象上添加右键事件监听
      const _this = this
      document.querySelector('.upper-canvas').onmousedown = function(e) {
        if (e.button === 2) {
          if (_this.pointArray.length > 0) {
            _this.pointArray.map((point, index) => {
              _this.canvas.remove(point)
            })
            _this.lineArray.map((line, index) => {
              _this.canvas.remove(line)
            })
            _this.canvas.remove(_this.activeShape).remove(_this.activeLine)

            _this.activeLine = null
            _this.activeShape = null
            _this.pointArray = [] // 顶点集合
            _this.lineArray = [] // 线集合
          } else if (_this.canvas.getActiveObjects().length > 0) {
            _this.rightShow(e)
          }
        }
      }
    },
    disabledItem(id) {
      if (this.groupList.length > 0) {
        let list = []
        this.groupList.forEach(item => {
          list = list.concat(item.value)
        })
        const newlist = list.map(item => {
          return item.id
        })
        if (newlist.indexOf(id) !== -1 && id !== this.currentId) {
          return true
        } else {
          return false
        }
      } else {
        return false
      }
    },
    rightShow(e) {
      const menu = this.$refs.msgRightMenu
      this.isPersoncontextMenus = true
      var evt = event || window.event

      // 给left和top分别赋值为鼠标的位置；
      menu.style.left = evt.pageX + 'px'
      menu.style.top = evt.pageY + 'px'
    }
  }
}
</script>

<style lang="scss" scoped>
  .el-container {
    flex-direction: column;
  }

  img,
  input {
    display: none;
  }

  .demo {
    display: flex;
    flex-direction: column;
    align-items: center;

    .canvas-content {
      width: 100%;
      display: flex;

      .left,
      .right {
        display: flex;
        flex: 0 0 auto;
        align-items: center;
        font-size: 36px;
        width: 36px;

        button {
          width: 36px;
          height: 36px;
          border-radius: 50%;
          border: none;
          background-color: rgba(31, 45, 61, .11);
          color: #fff;
        }

        button:hover {
          background-color: rgba(31, 45, 61, .23);
        }
      }

      .left {
        margin-right: 4px;
      }

      .right {
        margin-left: 4px;
      }

      .canvas-main {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }

  canvas {
    border: 1px dashed black;
    box-sizing: border-box;
  }

  .describe {
    display: flex;
    margin-top: 20px;

    .describe-title {
      flex: 0 0 auto;
    }
  }

  .position-contentor {
    margin-bottom: 20px;
    display: flex;
    justify-content: space-between;
  }

  .btn-contentor {
    text-align: center;
    margin-top: 10px;
  }

  /deep/ .el-dialog__wrapper {
    display: flex;
    align-items: center;
  }

  /* //css样式直供参考，根据自己的需要写样式 */
  #menu {
    list-style: none;
    margin: 0px;
    padding: 0px;
    position: absolute;
    height: 136px;
    overflow: auto;
    background-color: #fff;
    position: fixed;
    border: 1px solid #cecece;
    border-radius: 4px;
    min-width: 120px;
    ul {
      padding: 0px;
      margin: 0px;
    }

    li {
      cursor: pointer;
      margin: 0px;
      font-size: 14px;
      padding: 0 20px;
      position: relative;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #606266;
      height: 34px;
      line-height: 34px;
      box-sizing: border-box;
      cursor: pointer;
    }

    li:hover {
      background-color: #f5f7fa;
    }

    .is-disabled {
      color: #c0c4cc;
      cursor: not-allowed;
      pointer-events: none;
    }

    .active {
      color: #409eff;
    }
  }

</style>
